home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Chans / fax / ps250 / ps250_intf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  13.2 KB  |  630 lines

  1. /* ps250_intf.c: interface routines for Panasonic 250 driver */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_intf.c,v 6.0 1991/12/18 20:07:26 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_intf.c,v 6.0 1991/12/18 20:07:26 jpo Rel $
  9.  *
  10.  * $Log: ps250_intf.c,v $
  11.  * Revision 6.0  1991/12/18  20:07:26  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15. #include    "util.h"
  16. #include    "retcode.h"
  17. #include    "qmgr.h"
  18. #include    "chan.h"
  19. #include    "IOB-types.h"
  20. #include    "../faxgeneric.h"
  21. #include     "ps250.h"
  22.  
  23. /*
  24.  *    Heuristics for whether to bounce or not on failure
  25.  */
  26.  
  27. extern int table_verified;
  28.  
  29. static void isPermanentFail(faxctl)
  30. FaxCtlr    *faxctl;
  31. {
  32.     PsModem    *psm = PSM(faxctl);
  33.     /* set qmgrErrCode to negativeDR in certain situations */
  34.     
  35.     if (psm->connected == FALSE)
  36.         /* no connection so not permanent */
  37.         faxctl->qmgrErrCode = int_Qmgr_status_messageFailure;
  38.     else {
  39.         /* connected */
  40.         if (table_verified == TRUE)
  41.             /* in table so not permanent */
  42.             faxctl->qmgrErrCode = int_Qmgr_status_messageFailure;
  43.         else
  44.             faxctl->qmgrErrCode = int_Qmgr_status_negativeDR;
  45.     }
  46. }
  47.  
  48. /*
  49.  *     Open ps250 device and initialize
  50.  *    Return OK or NOTOK
  51.  */
  52.  
  53. psOpen (faxctl)
  54. FaxCtlr    *faxctl;
  55. {
  56.     PsModem    *psm = PSM(faxctl);
  57.     
  58.     if (openPsModem(psm) != OK) {
  59.         sprintf(faxctl->errBuf,
  60.             "openPsModem failed [%s]",
  61.             psm->errBuf);
  62.         PP_LOG(LLOG_EXCEPTIONS,
  63.                ("%s", faxctl->errBuf));
  64.         return NOTOK;
  65.     }
  66.     return OK;
  67. }
  68.  
  69. /*
  70.  *     Close fax device
  71.  */
  72.  
  73. psClose (faxctl)
  74. FaxCtlr    *faxctl;
  75. {
  76.     PsModem    *psm = PSM(faxctl);
  77.     
  78.     return closePsModem(psm);
  79. }
  80.  
  81. /*
  82.  *    Initialise for transmission
  83.  */
  84.  
  85. extern CHAN    *mychan;
  86.  
  87. static int isValidPhoneChar (ch)
  88. char    ch;
  89. {
  90.     if (isdigit(ch)
  91.         || isspace(ch))
  92.         return OK;
  93.     switch (ch) {
  94.         case '-':
  95. /*    case '+': tested for explicitly */
  96.         return OK;
  97.         default:
  98.         break;
  99.     }
  100.     return NOTOK;
  101. }
  102.         
  103. static int convertPhoneNumber(psm, from, to, pfatal)
  104. PsModem    *psm;
  105. char    *from;
  106. char    *to;
  107. int    *pfatal;
  108. {
  109.     char    *ifrom = from, *ito = to;
  110.     char    intprefix[FAX_TELNOSIZE];
  111. #define    INT_PREFIX    "int_prefix"    
  112. #define    PAUSE        0x3F
  113.     while (*ifrom != '\0' && isspace(*ifrom)) *ifrom++;
  114.     
  115.     *pfatal = FALSE;
  116.  
  117.     if (psm->phone_prefix) {
  118.         /* insert phone prefix */
  119.         char *ix = psm->phone_prefix;
  120.         while (*ix != '\0' && (ito - to) < FAX_TELNOSIZE) {
  121.             if (isValidPhoneChar(*ix) != OK) {
  122.                 PP_LOG(LLOG_EXCEPTIONS,
  123.                        ("Illegal phone character '%c' in prefix '%s'",
  124.                     *ix, psm->phone_prefix));
  125.                 to[0] = '\0';
  126.                 sprintf(psm->errBuf,
  127.                     "Illegal character '%c'",
  128.                     *ix);
  129.                 return NOTOK;
  130.             }
  131.             if (isspace(*ix) ||
  132.                 *ix == '-')
  133.                 ito++;
  134.             else
  135.                 *ito++ = *ix++;
  136.         }
  137.     }
  138.  
  139.     if (*ifrom == '+') {
  140.         /* insert national prefix */
  141.         ifrom++;
  142.         if (mychan && 
  143.             mychan -> ch_table && 
  144.             tb_k2val (mychan -> ch_table, 
  145.                   INT_PREFIX, intprefix, TRUE) != NOTOK) {
  146.             char    *ix = &(intprefix[0]);
  147.             while (*ix != '\0' && 
  148.                    (ito - to) < FAX_TELNOSIZE) {
  149.                 if (isValidPhoneChar(*ix) != OK) {
  150.                     PP_LOG(LLOG_EXCEPTIONS,
  151.                            ("Illegal phone character '%c' in international prefix '%s'",
  152.                         *ix, intprefix));
  153.                     to[0] = '\0';
  154.                     sprintf(psm->errBuf,
  155.                         "Illegal character '%c'",
  156.                         *ix);
  157.                     return NOTOK;
  158.                 }
  159.                 if (isspace(*ix) ||
  160.                     *ix == '-')
  161.                     ito++;
  162.                 else
  163.                     *ito++ = *ix++;
  164.                 
  165.             }
  166.         }
  167.     }
  168.  
  169.     /* any errors from here in are bad errors */
  170.     *pfatal = TRUE;
  171.     while (*ifrom != '\0' && 
  172.            (ito - to) < FAX_TELNOSIZE) {
  173.         if (isValidPhoneChar(*ifrom) != OK) {
  174.             PP_LOG(LLOG_EXCEPTIONS,
  175.                    ("Illegal phone character '%c' in  '%s'",
  176.                 *ifrom, from));
  177.             sprintf(psm->errBuf,
  178.                 "Illegal character '%c'",
  179.                 *ifrom);
  180.             to[0] ='\0';
  181.             return NOTOK;
  182.         }
  183.         if (isspace(*ifrom) ||
  184.             *ifrom == '-')
  185.             ifrom++;
  186.         else if (*ifrom == 'P' 
  187.              || *ifrom == 'p') {
  188.             *ito = PAUSE;
  189.             *ifrom++;
  190.         } else
  191.             *ito++ = *ifrom++;
  192.     }
  193.     if ((ito - to) >= FAX_TELNOSIZE) {
  194.         PP_LOG(LLOG_EXCEPTIONS,
  195.                ("Phone number '%s' is too long. Maximum is %d",
  196.             from, FAX_TELNOSIZE));
  197.         sprintf(psm->errBuf,
  198.             "Number too long (max=%d)",
  199.             FAX_TELNOSIZE);
  200.         to[0] = '\0';
  201.         return NOTOK;
  202.     }
  203.     *ito = '\0';
  204.     return OK;
  205. }
  206.  
  207. psInitXmit (faxctl)
  208. FaxCtlr    *faxctl;
  209. {
  210.     char    telno[FAX_TELNOSIZE];
  211.     int     drit = FALSE;
  212.     PsModem    *psm = PSM(faxctl);
  213.  
  214.     faxctl->qmgrErrCode = int_Qmgr_status_messageFailure;
  215.     
  216.     if (convertPhoneNumber (psm, faxctl->telno, telno, &drit) != OK) {
  217.         sprintf(faxctl->errBuf,
  218.             "Unable to convert telephone number '%s' [%s]",
  219.             faxctl->telno, psm->errBuf);
  220.         PP_LOG(LLOG_EXCEPTIONS,
  221.                ("%s", faxctl->errBuf));
  222.         if (drit == TRUE
  223.             && table_verified != TRUE)
  224.             /* bad user given phone number */
  225.             faxctl->qmgrErrCode = int_Qmgr_status_negativeDR;
  226.         return RP_MECH;
  227.     }
  228.  
  229.     if (dialPsModem(psm, telno) != OK) {
  230.         sprintf(faxctl->errBuf,
  231.             "Unable to initial Xmit [%s]",
  232.             psm->errBuf);
  233.         PP_LOG(LLOG_EXCEPTIONS,
  234.                ("%s", faxctl->errBuf));
  235.         isPermanentFail(faxctl);
  236.         return NOTOK;
  237.     }
  238.     return OK;
  239. }
  240.  
  241. /*
  242.  *    Abort the current call to the fax machine
  243.  */
  244.  
  245. psAbort (faxctl)
  246. FaxCtlr    *faxctl;
  247. {
  248.     PsModem    *psm = PSM(faxctl);
  249.     abortPsModem(psm);
  250. }
  251.  
  252. /*
  253.  *    Terminate transmission
  254.  */
  255.  
  256. psTermXmit (faxctl)
  257. FaxCtlr    *faxctl;
  258. {
  259.     PsModem    *psm = PSM(faxctl);
  260.     if (eomPsModem(psm) != OK) {
  261.         sprintf(faxctl->errBuf,
  262.             "Bad termination of transmission [%s]",
  263.             psm->errBuf);
  264.         PP_LOG(LLOG_EXCEPTIONS,
  265.                ("%s", faxctl->errBuf));
  266.         isPermanentFail(faxctl);
  267.         return NOTOK;
  268.     }
  269.     return OK;
  270. }
  271.  
  272. /*
  273.  *    Test/Set G3 Fax Parameters
  274.  */
  275.  
  276. psSetG3Params (faxctl, params)
  277. FaxCtlr    *faxctl;
  278. struct type_IOB_G3FacsimileParameters *params;
  279. {
  280.         PsModem    *psm = PSM(faxctl);
  281.  
  282.         if (params -> non__basic__parameters) {
  283.                 if (bit_test(params -> non__basic__parameters,
  284.                              bit_MTA_G3FacsimileNonBasicParameters_two__dimensional) == 1) {
  285.                         sprintf(faxctl->errBuf,
  286.                                 "Unable to deal with two dimensional fax");
  287.                         PP_LOG(LLOG_EXCEPTIONS,
  288.                                ("%s", faxctl->errBuf));
  289.                         return NOTOK;
  290.                 }
  291.  
  292.                 if (bit_test(params -> non__basic__parameters,
  293.                              bit_MTA_G3FacsimileNonBasicParameters_uncompressed) == 1) {
  294.                         sprintf(faxctl->errBuf,
  295.                                 "Unable to deal with uncompressed fax");
  296.                         PP_LOG(LLOG_EXCEPTIONS,
  297.                                ("%s", faxctl->errBuf));
  298.                         return NOTOK;
  299.                 }
  300.                 
  301.                 if (bit_test(params -> non__basic__parameters,
  302.                              bit_MTA_G3FacsimileNonBasicParameters_fine__resolution) == 1) {
  303.             sprintf(faxctl->errBuf,
  304.                 "Unable to deal with fine resolution");
  305.             PP_LOG(LLOG_EXCEPTIONS,
  306.                    ("%s", faxctl->errBuf));
  307.             return NOTOK;
  308.         }
  309.         }
  310.     if (psModemG3init(psm) != OK) {
  311.         sprintf(faxctl->errBuf,
  312.             "Failed to initialise modem for fax transmission [%s]",
  313.             psm->errBuf);
  314.         PP_LOG(LLOG_EXCEPTIONS,
  315.                ("%s", faxctl->errBuf));
  316.         return NOTOK;
  317.     }
  318.         return OK;
  319. }
  320.  
  321. /*
  322.  *    Send page of G3 fax to fax modem
  323.  */
  324.  
  325.  
  326. /*
  327.  *    reverse bit orderings
  328.  */
  329.  
  330. void reverse_strb(str, len)
  331. char    str[];
  332. int    len;
  333. {
  334.     int    i;
  335.     for (i = 0; i < len; i++)
  336.         str[i] = flip_bits((unsigned char) str[i]);
  337. }
  338.  
  339. psSendPage (faxctl, str, len, last)
  340. FaxCtlr    *faxctl;
  341. char    *str;
  342. int    len;
  343. int    last;
  344. {
  345.     PsModem    *psm = PSM(faxctl);
  346.  
  347.     /* G3Fax encoding is reverse bit ordering of X400 encoding */
  348.     reverse_strb(str, len);
  349.  
  350.     return sendPsModem(psm, str, len, last);
  351. }
  352.  
  353. /*
  354.  *    Set IA5 transmission parameters
  355.  */
  356.  
  357. psSetIA5Params (faxctl)
  358. FaxCtlr    *faxctl;
  359. {
  360.     PsModem    *psm = PSM(faxctl);
  361.  
  362.     if (psModemIA5init(psm) != OK) {
  363.         sprintf(faxctl->errBuf,
  364.             "Failed to initialise modem for ia5 transmission [%s]",
  365.             psm->errBuf);
  366.         PP_LOG(LLOG_EXCEPTIONS,
  367.                ("%s", faxctl->errBuf));
  368.         return NOTOK;
  369.     }
  370.         return OK;
  371. }
  372.     
  373. /*
  374.  *    Send page of ia5 to fax modem
  375.  */
  376.  
  377. psSendIA5File (faxctl, fileName, last)
  378. FaxCtlr    *faxctl;
  379. char    *fileName;
  380. int    last;
  381. {
  382.     PsModem    *psm = PSM(faxctl);
  383.     FILE    *fp;
  384.  
  385.     if ((fp = fopen (fileName, "r")) == (FILE *) 0) {
  386.         PP_SLOG (LLOG_EXCEPTIONS, fileName,
  387.              ("Can't open file"));
  388.         sprintf(faxctl->errBuf,
  389.             "Unable to open IA5 file '%s'",
  390.             fileName);
  391.         return NOTOK;
  392.     }
  393.  
  394.     if (sendPsModemIA5 (psm, fp, last) != OK) {
  395.         sprintf(faxctl->errBuf,
  396.             "failed to send ia5 file [%s]",
  397.             psm->errBuf);
  398.         PP_LOG(LLOG_EXCEPTIONS,
  399.                ("%s", faxctl->errBuf));
  400.         fclose(fp);
  401.         return NOTOK;
  402.     } 
  403.     fclose(fp);
  404.     return OK;
  405. }
  406.  
  407. /*
  408.  *    Wait for and store inbound faxes
  409.  */
  410.  
  411. psReceiveG3Fax (faxctl, pg3fax)
  412. FaxCtlr    *faxctl;
  413. struct type_IOB_G3FacsimileBodyPart     **pg3fax;
  414. {
  415.     PsModem    *psm = PSM(faxctl);
  416.     /* open */
  417.     if (faxctl->open != NULLIFP
  418.         && (*faxctl->open) (faxctl) != OK) {
  419.         PP_LOG(LLOG_EXCEPTIONS,
  420.                ("fax open failed ['%s']",
  421.             faxctl->errBuf));
  422.         return NOTOK;
  423.     }
  424.     /* wait */
  425.     if (ps_wait_for_fax (psm) != OK) {
  426.         PP_LOG(LLOG_EXCEPTIONS,
  427.                ("ps_wait_for_fax failed ['%s']",
  428.             faxctl->errBuf));
  429.         return NOTOK;
  430.     }
  431.     /* scan */
  432.     if (ps_init_listen (psm) != OK) {
  433.         PP_LOG(LLOG_EXCEPTIONS,
  434.                ("ps_init_fax_listen failed ['%s']",
  435.             faxctl->errBuf));
  436.         return NOTOK;
  437.     }
  438.     ps_wait_for_data(psm);
  439.     
  440.     if (rcvPsModem (psm, pg3fax) != OK) {
  441.         PP_LOG(LLOG_EXCEPTIONS,
  442.                ("ps_fax_read_bitstrings failed ['%s']",
  443.             faxctl->errBuf));
  444.         return NOTOK;
  445.     }
  446.     /* close */
  447.     if (faxctl->close != NULLIFP)
  448.         (*faxctl->close)(faxctl);
  449.  
  450.     return OK;
  451. }
  452.  
  453. /*
  454.  *    Parse out-info line arguments
  455.  */
  456.  
  457. psArgParseOut (faxctl, key, value)
  458. FaxCtlr    *faxctl;
  459. char    *key;
  460. char    *value;
  461. {
  462.     PsModem    *psm = PSM(faxctl);
  463.  
  464.     if (!isstr(value)) {
  465.         sprintf(faxctl->errBuf,
  466.             "No value given with key '%s'",
  467.             key);
  468.         PP_LOG (LLOG_EXCEPTIONS,
  469.             ("%s", faxctl->errBuf));
  470.         return NOTOK;
  471.     }
  472.  
  473.         if (lexequ(key, "out") == 0)
  474.             strcpy(psm->devName, value);
  475.         else if (lexequ(key, "prefix") == 0) 
  476.                 psm->phone_prefix = strdup(value);
  477.     else if (lexequ(key, "nattempts") == 0) {
  478.         if ((psm->nattempts = atoi(value)) <= 0) {
  479.             sprintf(faxctl->errBuf,
  480.                 "Cannot set number of attempts to '%s'",
  481.                 value);
  482.             PP_LOG(LLOG_EXCEPTIONS,
  483.                    ("%s", faxctl->errBuf));
  484.             return NOTOK;
  485.         }
  486.     } else if (lexequ(key, "sleep") == 0) {
  487.         if ((psm->sleepFor = atoi(value)) <= 0) {
  488.             sprintf(faxctl->errBuf,
  489.                 "Cannot set sleep time to '%s'",
  490.                 value);
  491.             PP_LOG(LLOG_EXCEPTIONS,
  492.                    ("%s", faxctl->errBuf));
  493.             return NOTOK;
  494.         }
  495.     } else if (lexequ(key, "softcar") == 0) {
  496.         if (lexequ(value, "used") == 0)
  497.             psm->softcar = TRUE;
  498.     }
  499.     else {
  500.         sprintf(faxctl->errBuf,
  501.             "Unknown info arg '%s=%s",
  502.             key, (isstr(value)) ? value : "(null)");
  503.         return NOTOK;
  504.     }
  505.     return OK;
  506. }
  507.  
  508. /*
  509.  *    Parse out-info line arguments
  510.  */
  511.  
  512. psArgParseIn (faxctl, key, value)
  513. FaxCtlr    *faxctl;
  514. char    *key;
  515. char    *value;
  516. {
  517.     PsModem    *psm = PSM(faxctl);
  518.     
  519.     if (!isstr(value)) {
  520.         sprintf(faxctl->errBuf,
  521.             "No value given with key '%s'",
  522.             key);
  523.         PP_LOG (LLOG_EXCEPTIONS,
  524.             ("%s", faxctl->errBuf));
  525.         return NOTOK;
  526.     }
  527.  
  528.         if (lexequ(key, "in") == 0)
  529.                 strcpy(psm->devName, value);
  530.         else if (lexequ(key, "master") == 0)
  531.                 strcpy(faxctl->fax_recip,value);
  532.     else if (lexequ(key, "subject") == 0)
  533.          strcpy(faxctl->subject, value);
  534.     else if (lexequ(key, "softcar") == 0) {
  535.         if (lexequ(value, "used") == 0)
  536.             psm->softcar = TRUE;
  537.     }
  538.     else {
  539.         sprintf(faxctl->errBuf,
  540.             "Unknown info arg '%s=%s",
  541.             key, (isstr(value)) ? value : "(null)");
  542.         return NOTOK;
  543.     }
  544.     return OK;
  545. }
  546.  
  547. /*
  548.  *    Return a fax control block
  549.  */
  550.  
  551. extern int      optind;
  552. extern char     *optarg;
  553.  
  554. FaxCtlr    *init_faxctrlr(type, argc, argv)
  555. int    type;
  556. int    argc;
  557. char    **argv;
  558. {
  559.     FaxCtlr    *faxctl;
  560.     PsModem    *psm;
  561.     int    opt;
  562.  
  563.     faxctl = (FaxCtlr *)malloc(sizeof(FaxCtlr));
  564.         bzero(faxctl, sizeof(FaxCtlr));
  565.  
  566.     psm = (PsModem *)malloc(sizeof(PsModem));
  567.     bzero(psm, sizeof(PsModem));
  568.     switch (type) {
  569.         case FAX_OUTBOUND:
  570.         psm->nattempts = 3;
  571.         psm->sleepFor = 30; /* 1/2 min */
  572.         psm->polled = FALSE;
  573.         sprintf(psm->devName, "/dev/faxout"); /* default for now */
  574.         faxctl->setG3Params = psSetG3Params;
  575.         faxctl->sendPage = psSendPage;
  576.         faxctl->setIA5Params = psSetIA5Params;
  577.         faxctl->sendIA5File = psSendIA5File;
  578.         faxctl->arg_parse = psArgParseOut;
  579.         break;
  580.         case FAX_INBOUND:
  581.         sprintf(psm->devName, "/dev/faxin");
  582.         sprintf(faxctl->channel, "fax");
  583.         sprintf(faxctl->fax_recip, "faxmaster");
  584.         sprintf(faxctl->subject, "Inbound fax message");
  585.         faxctl->receiveG3Fax = psReceiveG3Fax;
  586.         psm->nattempts = 1;
  587.         faxctl->arg_parse = psArgParseIn;
  588.         
  589.         /* now deal with command line args */
  590.         
  591.         while ((opt = getopt(argc, argv, "c:")) != EOF)
  592.             switch(opt) {
  593.                 case 'c':
  594.                 /* override channel name */
  595.                 strcpy(faxctl->channel, optarg);
  596.                 break;
  597.                 default:
  598.                 (void) sprintf(faxctl->errBuf,
  599.                            "Unknown command line argument '-%c'",
  600.                            (char) opt);
  601.                 PP_LOG(LLOG_EXCEPTIONS,
  602.                        ("%s", faxctl->errBuf));
  603.                 free(psm);
  604.                 free(faxctl);
  605.                 return (FaxCtlr *) NULL;
  606.             
  607.                 break;
  608.             }
  609.         break;
  610.         default:
  611.         PP_LOG(LLOG_EXCEPTIONS,
  612.                ("Unsupported fax type '%d'", type));
  613.         free(psm);
  614.         free(faxctl);
  615.         return (FaxCtlr *) NULL;
  616.     }
  617.  
  618.     psm->softcar = FALSE;
  619.     psm->resolution = FAX_PARAM1_RES385;
  620.     faxctl->softc = (char *) psm;
  621.  
  622.     faxctl->open = psOpen;
  623.     faxctl->close = psClose;
  624.     faxctl->initXmit = psInitXmit;
  625.     faxctl->abort = psAbort;
  626.     faxctl->termXmit = psTermXmit;
  627.     
  628.     return faxctl;
  629. }
  630.